package com.ymatou.iapi.optrade.testcase;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;

import com.ymatou.iapi.optrade.parameter.enums.LogisticsTypeEnum;
import com.ymatou.iapi.optrade.parameter.req.GetOrderGroupInfosReq;
import com.ymatou.iapi.optrade.parameter.req.PlaceOrderReq;
import com.ymatou.iapi.optrade.parameter.vo.OrderGroupVo;
import com.ymatou.iapi.optrade.parameter.vo.OrderItemVo;
import com.ymatou.iapi.optrade.parameter.vo.OrderVo;
import com.ymatou.iapi.optrade.resp.GetOrderGroupInfosResp;
import com.ymatou.iapi.optrade.resp.OrderInfo;
import com.ymatou.iapi.optrade.resp.ProductInfo;
import com.ymatou.iapi.optrade.resp.TradingServiceResp;
import com.ymatou.iapi.optrade.service.GetOrderGroupInfosCall;
import com.ymatou.iapi.userregister.parameter.UserRegisterInfoRequestDtoBean;
import com.ymt.core.tool.Logger;
import com.ymt.utils.annotation.TestCase;
import com.ymt.utils.annotation.TestSuite;
import com.ymt.utils.tag.P1;
import com.ymttest.business.service.AccountCallServiceV2;
import com.ymttest.business.service.JUserCallService;
import com.ymttest.business.service.YMTTrading.TradingCallService;
import com.ymttest.business.service.YMTTrading.TradingPlaceOrderCallService;
import com.ymttest.business.service.YMTTrading.TradingProductVo;
import com.ymttest.database.sharding.db.ext.model.OrderExtPo;
import com.ymttest.database.sharding.db.sharding.model.OrderPo;
import com.ymttest.database.sharding.db.sqlwapper.OrderShardingWapper;
import com.ymttest.database.sharding.db.sqlwapper.OrderWapper;
import com.ymttest.utils.DataUtil;
import com.ymttest.utils.EnvSetup;

/**
 *  支付之前查询主单信息(防止买家查询服务异常,导致无法下单支付)
 */
@TestSuite
public class Ts_GetOrderGroupInfos {

	private static GetOrderGroupInfosReq req;
	private static GetOrderGroupInfosCall getOrderGroupInfosCall;
	
	private static OrderShardingWapper orderShardingWapper = new OrderShardingWapper();
	private static OrderWapper orderWapper = new OrderWapper();

	@BeforeClass
	public static void setUp() {
		Logger.createResultFile("支付之前查询主单信息");
	}

	@Before
	public void caseUp() {
		req = new GetOrderGroupInfosReq();
		getOrderGroupInfosCall = new GetOrderGroupInfosCall();
	}

	@AfterClass
	public static void tearDown() {
		Logger.generateResult(getOrderGroupInfosCall.getOpurl());
		orderShardingWapper.activeDeadCommunicationsLink(orderShardingWapper);
	}

	@After
	public void caseDown() {
		Logger.end();
	}

	private GetOrderGroupInfosResp constructExpectedResult() {

		GetOrderGroupInfosResp resp = new GetOrderGroupInfosResp();
		
		List<OrderPo> orderPoList = orderShardingWapper
				.selectOrderbyMainOrderId(req.getOrderGroupId());

		List<Long> orderList = orderPoList.stream().map(OrderPo::getOrderId)
				.collect(Collectors.toList());

		List<OrderExtPo> orderExtPoList = new ArrayList<OrderExtPo>();

		orderList.forEach(orderId -> {

			orderExtPoList.add(orderWapper.selectOrderExtByOrderId(orderId));

		});

		try {

			Map<Long, OrderInfo> map = new HashMap<Long, OrderInfo>();

			for (OrderPo po : orderPoList) {

				if (!map.containsKey(po.getOrderId())) {

					OrderInfo orderInfo = new OrderInfo();

					orderInfo.setOrderId(po.getOrderId());
					orderInfo.setSellerId(po.getSellerId());

					Optional<OrderExtPo> orderExt = orderExtPoList
							.stream()
							.filter(ext -> ext.getOrderId().equals(
									po.getOrderId())).findFirst();

					if (orderExt.isPresent()) {

						orderInfo.setReceiver(orderExt.get().getReceiver());

					}
					
					orderInfo
							.setNeedUploadIdCard(po.getNeedUploadIdcard() == null ? false
									: po.getNeedUploadIdcard() && !(po.getUploadedIdcard() == null ? false : po.getUploadedIdcard()));

					orderInfo.setPayableAmount(po.getPayableAmount());

					orderInfo.setProducts(new ArrayList<ProductInfo>());

					map.put(po.getOrderId(), orderInfo);

				}

				ProductInfo productInfo = new ProductInfo();

				productInfo.setLogisticsType(po.getLogisticsType());

				LogisticsTypeEnum logisticsTypeEnum = LogisticsTypeEnum
						.findEnumByCode(po.getLogisticsType());

				productInfo
						.setBonded(logisticsTypeEnum == LogisticsTypeEnum.BondedDelivery);

				map.get(po.getOrderId()).getProducts().add(productInfo);

			}

			resp.setTradingId(req.getOrderGroupId());
			resp.setOrderInfos(map.values().stream()
					.collect(Collectors.toList()));

			if (req.getNeedAccountAmount() == null ? false : req.getNeedAccountAmount()) {

				BigDecimal accountBalance = AccountCallServiceV2
						.getAccountBalance((int) req.getUserId(), 1);
				resp.setAccountAmount(accountBalance);
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
		return resp;
	}
	
	/**
	 * 一个订单下面多个商品, 老买手，新用户
	 * 
	 * 一单所在日期之后的其他订单（同一买家在该买手店铺支付完成的订单）为该买手的老客订单
	 */
	@SuppressWarnings({ "rawtypes", "unused", "static-access" })
	private TradingServiceResp placeOrder6() throws Exception {

		// 注册新用户
		Map newUser = new HashMap();

		UserRegisterInfoRequestDtoBean urb = new JUserCallService()
				.initUserRegisterInfoRequestDtoBean();

		long userId = new JUserCallService()
				.UserRegisterInfoRequestDtoCall(urb).getUserid();
		
		String accountid1 = AccountCallServiceV2.getAccountId((int)userId);
		AccountCallServiceV2.resetAccount(accountid1, new BigDecimal(90000000), new BigDecimal(0));

		long sellerId = Long.valueOf(EnvSetup.getData("SellerId"));

		String sellerName = String.valueOf(EnvSetup.getData("SellerName"));

		PlaceOrderReq placeOrderReq = TradingCallService
				.buildStandPlaceOrderReq();
		
		OrderGroupVo orderGroupVo = TradingCallService.createOrderGroupVo(sellerId, sellerName);
		OrderVo orderVo = TradingCallService.createOrderVo();
		
		// 创建一个普通商品
		TradingProductVo product = TradingProductVo.createPro(sellerId,
				sellerName, 100);
		
		OrderItemVo orderItemVo = TradingCallService.createOrderItemVo(
				product.getProductId(), product.getCatalogId());
		
		orderVo.setOrderItems(Arrays.asList(orderItemVo));
		orderGroupVo.setOrders(Arrays.asList(orderVo));
		placeOrderReq.setOrderGroups(Arrays.asList(orderGroupVo));

		placeOrderReq.setUserId(userId);

		return TradingCallService.callPlaceOrderService(placeOrderReq);

	}

	private void verify() {
		GetOrderGroupInfosResp expectResponse = constructExpectedResult();
		GetOrderGroupInfosResp actualResponse = getOrderGroupInfosCall
				.getBuyerGroupOrderInfosResp();

		List<OrderInfo> expectOrders = expectResponse.getOrderInfos();
		List<OrderInfo> actualOrders = actualResponse.getOrderInfos();

		DataUtil.verifyDecimalEquals(expectResponse.getAccountAmount(),
				actualResponse.getAccountAmount(), "accountAmount");

		for (int i = 0; i < expectOrders.size(); i++) {

			OrderInfo expect = expectOrders.get(i);
			OrderInfo actual = actualOrders.get(i);

			Logger.verifyEquals(expect.getOrderId(), actual.getOrderId(), "订单号");

			Logger.verifyEquals(expect.getPlatform(), actual.getPlatform(),
					"platform");

			Logger.verifyEquals(expect.getSellerId(), actual.getSellerId(),
					"sellerId");

			DataUtil.verifyDecimalEquals(expect.getPayableAmount(),
					actual.getPayableAmount(), "payableAmount");

			/*			Logger.verifyEquals(expect.getLastPayTime(),
								actual.getLastPayTime(), "lastPayTime");*/

			Logger.verifyEquals(expect.getReceiver(), actual.getReceiver(),
					"receiver");

			Logger.verifyEquals(expect.isNeedUploadIdCard(),
					actual.isNeedUploadIdCard(), "needUploadIdCard");

			List<ProductInfo> expectProductInfo = expect.getProducts();
			List<ProductInfo> actualProductInfo = actual.getProducts();

			for (int j = 0; j < expectProductInfo.size(); j++) {

				Logger.verifyEquals(
						expectProductInfo.get(j).getLogisticsType(),
						actualProductInfo.get(j).getLogisticsType(),
						"logisticsType");
			}

		}
	}
	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_GetOrderGroupInfos_001() {
		Logger.start(true, "订单状态为1 下单,根据主单号获取订单详情");
		try {

			TradingServiceResp placeOrderResp = TradingPlaceOrderCallService
					.placeOrderWithLuxury(false);

			long userId = placeOrderResp.getUserId();
			long tradingId = placeOrderResp.getTradingId();

			req.setUserId(userId);
			req.setOrderGroupId(tradingId);
			req.setNeedAccountAmount(false);

			getOrderGroupInfosCall.setData(req);
			getOrderGroupInfosCall.callService();

			Logger.verifyEquals("200", getOrderGroupInfosCall.getCode(), "code");
			Logger.verifyEquals(0, getOrderGroupInfosCall.getBCode(), "bcode");

			verify();

		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_GetOrderGroupInfos_002() {
		Logger.start(true, "订单状态为2 付款,根据主单号获取订单详情");
		try {
			TradingServiceResp placeOrderResp = TradingCallService.payOrder();
			long userId = placeOrderResp.getUserId();
			long tradingId = placeOrderResp.getTradingId();

			req.setUserId(userId);
			req.setOrderGroupId(tradingId);
			req.setNeedAccountAmount(true);

			getOrderGroupInfosCall.setData(req);
			getOrderGroupInfosCall.callService();

			Logger.verifyEquals("200", getOrderGroupInfosCall.getCode(), "code");
			Logger.verifyEquals(0, getOrderGroupInfosCall.getBCode(), "bcode");

			verify();
		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_GetOrderGroupInfos_003() {
		Logger.start(true, "订单状态为3 取消订单,根据主单号获取订单详情");
		try {

			TradingServiceResp placeOrderResp = TradingCallService
					.cancelOrderAfterPaid();

			long userId = placeOrderResp.getUserId();
			long tradingId = placeOrderResp.getTradingId();

			req.setUserId(userId);
			req.setOrderGroupId(tradingId);
			req.setNeedAccountAmount(true);

			getOrderGroupInfosCall.setData(req);
			getOrderGroupInfosCall.callService();

			Logger.verifyEquals("200", getOrderGroupInfosCall.getCode(), "code");
			Logger.verifyEquals(0, getOrderGroupInfosCall.getBCode(), "bcode");

			verify();
		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_GetOrderGroupInfos_004() {
		Logger.start(true, "订单状态为 接单,根据主单号获取订单详情");
		try {
			TradingServiceResp placeOrderResp = TradingCallService
					.orderAccept();
			long userId = placeOrderResp.getUserId();
			long tradingId = placeOrderResp.getTradingId();

			req.setUserId(userId);
			req.setOrderGroupId(tradingId);
			req.setNeedAccountAmount(true);

			getOrderGroupInfosCall.setData(req);
			getOrderGroupInfosCall.callService();

			Logger.verifyEquals("200", getOrderGroupInfosCall.getCode(), "code");
			Logger.verifyEquals(0, getOrderGroupInfosCall.getBCode(), "bcode");

			verify();
		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_GetOrderGroupInfos_005() {
		Logger.start(true, "订单状态为 发货,根据主单号获取订单详情");
		try {
			TradingServiceResp placeOrderResp = TradingCallService
					.orderDelivery();

			long userId = placeOrderResp.getUserId();
			long tradingId = placeOrderResp.getTradingId();
			req.setNeedAccountAmount(true);

			req.setUserId(userId);
			req.setOrderGroupId(tradingId);

			getOrderGroupInfosCall.setData(req);
			getOrderGroupInfosCall.callService();

			Logger.verifyEquals("200", getOrderGroupInfosCall.getCode(), "code");
			Logger.verifyEquals(0, getOrderGroupInfosCall.getBCode(), "bcode");

			verify();
		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_GetOrderGroupInfos_006() {
		Logger.start(true, "订单状态为 确认收货根据主单号获取订单详情");
		try {
			TradingServiceResp placeOrderResp = TradingCallService
					.orderConfirmReceive();

			long userId = placeOrderResp.getUserId();
			long tradingId = placeOrderResp.getTradingId();
			req.setNeedAccountAmount(true);

			req.setUserId(userId);
			req.setOrderGroupId(tradingId);

			getOrderGroupInfosCall.setData(req);
			getOrderGroupInfosCall.callService();

			Logger.verifyEquals("200", getOrderGroupInfosCall.getCode(), "code");
			Logger.verifyEquals(0, getOrderGroupInfosCall.getBCode(), "bcode");

			verify();

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_GetOrderGroupInfos_007() {
		Logger.start(true, "订单状态为1 下单,查询账户余额，根据主单号获取订单详情");
		try {

			TradingServiceResp placeOrderResp = TradingCallService.payOrder();

			long userId = placeOrderResp.getUserId();
			long tradingId = placeOrderResp.getTradingId();
			req.setNeedAccountAmount(true);

			req.setUserId(userId);
			req.setOrderGroupId(tradingId);
			req.setNeedAccountAmount(true);

			getOrderGroupInfosCall.setData(req);
			getOrderGroupInfosCall.callService();

			Logger.verifyEquals("200", getOrderGroupInfosCall.getCode(), "code");
			Logger.verifyEquals(0, getOrderGroupInfosCall.getBCode(), "bcode");

			verify();

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_GetOrderGroupInfos_008() {
		Logger.start(true, "orderGroupId 为空");
		try {
			TradingServiceResp placeOrderResp = TradingCallService
					.orderConfirmReceive();

			long userId = placeOrderResp.getUserId();

			req.setUserId(userId);
			//req.setOrderGroupId(tradingId);

			getOrderGroupInfosCall.setData(req);
			getOrderGroupInfosCall.callService();

			Logger.verifyEquals("400", getOrderGroupInfosCall.getCode(), "code");
			Logger.verifyEquals(100, getOrderGroupInfosCall.getBCode(), "bcode");
			Logger.verifyEquals("orderGroupId:主单号不能为0",
					getOrderGroupInfosCall.getMsg(), "msg");
			verify();

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_GetOrderGroupInfos_009() {
		Logger.start(true, "userId 为空");
		try {
			TradingServiceResp placeOrderResp = TradingCallService
					.orderConfirmReceive();

			long tradingId = placeOrderResp.getTradingId();

			//req.setUserId(userId);
			req.setOrderGroupId(tradingId);

			getOrderGroupInfosCall.setData(req);
			getOrderGroupInfosCall.callService();

			Logger.verifyEquals("400", getOrderGroupInfosCall.getCode(), "code");
			Logger.verifyEquals(100, getOrderGroupInfosCall.getBCode(), "bcode");
			Logger.verifyEquals("userId:买家Id不能为0",
					getOrderGroupInfosCall.getMsg(), "msg");

			//verify();

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_GetOrderGroupInfos_010() {
		Logger.start(true, "needAccountAmount 为空");
		try {
			TradingServiceResp placeOrderResp = TradingCallService
					.orderConfirmReceive();

			long userId = placeOrderResp.getUserId();
			long tradingId = placeOrderResp.getTradingId();

			req.setUserId(userId);
			req.setOrderGroupId(tradingId);

			getOrderGroupInfosCall.setData(req);
			getOrderGroupInfosCall.callService();

			Logger.verifyEquals("200", getOrderGroupInfosCall.getCode(), "code");
			Logger.verifyEquals(0, getOrderGroupInfosCall.getBCode(), "bcode");

			verify();

		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	
	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_GetOrderGroupInfos_011() {
		Logger.start(true, "订单已支付");
		try {

			TradingServiceResp placeOrderResp = TradingCallService.payOrder();
			long userId = placeOrderResp.getUserId();
			long tradingId = placeOrderResp.getTradingId();

			req.setUserId(userId);
			req.setOrderGroupId(tradingId);
			req.setNeedAccountAmount(false);

			getOrderGroupInfosCall.setData(req);
			getOrderGroupInfosCall.callService();

			Logger.verifyEquals("200", getOrderGroupInfosCall.getCode(), "code");
			Logger.verifyEquals(0, getOrderGroupInfosCall.getBCode(), "bcode");

			verify();

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category(P1.class)
	@TestCase
	public void Tc_GetOrderGroupInfos_012() {
		Logger.start(true, "新用户下单,根据主单号获取订单详情");
		try {

			// 创建订单
			Logger.comment("前置数据准备");

			TradingServiceResp placeOrderResp = placeOrder6();

			long userId = placeOrderResp.getUserId();
			long tradingId = placeOrderResp.getTradingId();

			req.setUserId(userId);
			req.setOrderGroupId(tradingId);
			req.setNeedAccountAmount(true);

			getOrderGroupInfosCall.setData(req);
			getOrderGroupInfosCall.callService();

			Logger.verifyEquals("200", getOrderGroupInfosCall.getCode(), "code");
			Logger.verifyEquals(0, getOrderGroupInfosCall.getBCode(), "bcode");

			verify();

		} catch (Exception e) {
			Logger.fail(e);
		}
	}
}
